package com.firefly.admin.common.handle;

import com.baomidou.mybatisplus.core.toolkit.StringPool;
import com.firefly.admin.common.config.NettyConfig;
import com.firefly.admin.common.enums.ResultCodeEnum;
import com.firefly.admin.common.exception.BusinessException;
import com.firefly.admin.common.properties.WebSocketProperties;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;
import io.netty.handler.codec.http.websocketx.WebSocketServerProtocolHandler;
import io.netty.util.Attribute;
import io.netty.util.AttributeKey;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Slf4j
@Component
@ChannelHandler.Sharable
public class NettyServerTextHandler extends SimpleChannelInboundHandler<TextWebSocketFrame> {

    public static final String USER_ID = "userId";
    @Autowired
    private WebSocketProperties webSocketProperties;

    /**
     * 当客户端连接服务器完成就会触发该方法
     * 当 Channel 的连接建立并准备好接收数据时被调用。这意味着连接已经成功建立，可以开始发送和接收数据了。
     * 在每次连接激活时被调用
     */
    @Override
    public void channelActive(ChannelHandlerContext context) {
        log.info("客户端连接建立通道完成...可以开始发送数据..");
        Channel channel = context.channel();
        NettyConfig.getChannelGroup().add(channel);
    }

    @Override
    public void userEventTriggered(ChannelHandlerContext context, Object evt) throws Exception {
        if (evt instanceof WebSocketServerProtocolHandler.HandshakeComplete) {
            Channel channel = context.channel();
            WebSocketServerProtocolHandler.HandshakeComplete complete = (WebSocketServerProtocolHandler.HandshakeComplete) evt;
            String uri = complete.requestUri();
            System.out.println("uri: " + uri);
            if (StringUtils.isBlank(uri) || !uri.contains(webSocketProperties.getPath()) || !uri.contains(StringPool.QUESTION_MARK)) {
                throw new BusinessException(ResultCodeEnum.WEBSOCKET_USER_NOT_FOUND.getMsg());
            }
            String[] uriArray = uri.split(StringPool.BACK_SLASH + StringPool.QUESTION_MARK);
            if (uriArray.length < 1) {
                throw new BusinessException(ResultCodeEnum.WEBSOCKET_USER_NOT_FOUND.getMsg());
            }
            String[] paramsArray = uriArray[1].split(StringPool.EQUALS);
            if (paramsArray.length < 1) {
                throw new BusinessException(ResultCodeEnum.WEBSOCKET_USER_NOT_FOUND.getMsg());
            }
            String key = paramsArray[0];
            if (!USER_ID.equals(key)) {
                throw new BusinessException(ResultCodeEnum.WEBSOCKET_USER_NOT_FOUND.getMsg());
            }
            String value = paramsArray[1];
            AttributeKey<Object> userIdKey = AttributeKey.valueOf(USER_ID);
            channel.attr(userIdKey).set(value);
            NettyConfig.getChannelMap().put(value, channel);
            log.info("用户[{}]建立连接！", value);
            super.userEventTriggered(context, evt);
        }
    }

    @Override
    protected void channelRead0(ChannelHandlerContext context, TextWebSocketFrame textWebSocketFrame) {
        log.info("客户端===============: " + textWebSocketFrame.text());

    }

    @Override
    public void handlerRemoved(ChannelHandlerContext context) {
        try {
            Channel channel = context.channel();
            // 删除通道
            NettyConfig.getChannelGroup().remove(channel);
            removeUserId(channel);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext context, Throwable cause) {
        try {
            log.info("异常：{}", cause.getMessage());
            // 删除通道
            Channel channel = context.channel();
            NettyConfig.getChannelGroup().remove(channel);
            removeUserId(channel);
            context.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private void removeUserId(Channel channel) {
        try {
            Attribute<String> userIdKey = channel.attr(AttributeKey.valueOf(USER_ID));
            String userId = userIdKey.get();
            if (StringUtils.isNotBlank(userId)) {
                log.info("用户[{}]下线了!", userId);
                NettyConfig.getChannelMap().remove(userId);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
